"""
预订服务层
"""
from models import Reservation, Guest, Room, RoomStatus
from extension import db
from datetime import datetime
import uuid
from sqlalchemy.orm import joinedload
from mappers.reservation_mapper import ReservationMapper
from .base_service import BaseService


class ReservationService(BaseService):
    """预订业务逻辑"""
    
    def __init__(self):
        super().__init__(Reservation)
        self.mapper = ReservationMapper()
    
    def get_reservations_with_filters(self, page=1, per_page=10, room_number=None, status=None, 
                                     check_in_start=None, check_in_end=None):
        """获取预订列表（支持多条件过滤）"""
        from sqlalchemy.orm import contains_eager
        
        query = Reservation.query.join(Guest).join(Room).options(
            contains_eager(Reservation.guest),
            contains_eager(Reservation.room).joinedload(Room.room_status)
        )
        
        if room_number:
            query = query.filter(Room.room_number.like(f'%{room_number}%'))
        if status is not None:
            query = query.filter(Reservation.status == status)
        if check_in_start:
            if isinstance(check_in_start, str):
                from datetime import datetime
                check_in_start = datetime.strptime(check_in_start, '%Y-%m-%d')
            query = query.filter(Reservation.check_in >= check_in_start)
        if check_in_end:
            if isinstance(check_in_end, str):
                from datetime import datetime
                check_in_end = datetime.strptime(check_in_end, '%Y-%m-%d')
            query = query.filter(Reservation.check_in <= check_in_end)
        
        return query.paginate(page=page, per_page=per_page, error_out=False, max_per_page=100)
    
    def get_reservation_detail(self, reservation_id):
        """获取预订详情"""
        return Reservation.query.options(
            joinedload(Reservation.guest),
            joinedload(Reservation.room).joinedload(Room.room_status)
        ).get(reservation_id)
    
    def create_reservation(self, guest_id, room_id, check_in, check_out, total_price, deposit=0):
        """创建预订"""
        # 验证客户是否存在
        if not Guest.query.get(guest_id):
            raise ValueError('客户不存在')
        
        # 验证房间是否存在
        if not Room.query.get(room_id):
            raise ValueError('房间不存在')
        
        # 检查房间在指定时间段是否可用
        conflicting = Reservation.query.filter(
            Reservation.room_id == room_id,
            Reservation.status != 4,  # 排除已取消的预订
            Reservation.check_in < check_out,
            Reservation.check_out > check_in
        ).first()
        
        if conflicting:
            raise ValueError('房间在指定时间段已被预订')
        
        # 生成预订编号
        reservation_number = f"RES-{datetime.now().strftime('%Y%m%d%H%M%S')}-{uuid.uuid4().hex[:6].upper()}"
        
        reservation = Reservation(
            reservation_number=reservation_number,
            guest_id=guest_id,
            room_id=room_id,
            check_in=check_in,
            check_out=check_out,
            status=1,  # 待确认
            total_price=total_price,
            deposit=deposit
        )
        db.session.add(reservation)
        db.session.commit()
        return reservation
    
    def update_reservation(self, reservation_id, **data):
        """更新预订信息"""
        reservation = self.get_reservation_detail(reservation_id)
        if not reservation:
            return None
        
        # 如果修改了房间或时间，需要检查可用性
        if ('room_id' in data or 'check_in' in data or 'check_out' in data):
            new_room_id = data.get('room_id', reservation.room_id)
            new_check_in = data.get('check_in', reservation.check_in)
            new_check_out = data.get('check_out', reservation.check_out)
            
            conflicting = Reservation.query.filter(
                Reservation.room_id == new_room_id,
                Reservation.id != reservation_id,
                Reservation.status != 4,
                Reservation.check_in < new_check_out,
                Reservation.check_out > new_check_in
            ).first()
            
            if conflicting:
                raise ValueError('房间在指定时间段已被预订')
        
        for key, value in data.items():
            if hasattr(reservation, key) and value is not None:
                setattr(reservation, key, value)
        
        db.session.commit()
        return reservation
    
    def confirm_reservation(self, reservation_id):
        """确认预订"""
        reservation = self.get_by_id(reservation_id)
        if not reservation:
            return None
        
        if reservation.status != 1:
            raise ValueError('只有待确认的预订才能确认')
        
        reservation.status = 2  # 已确认
        db.session.commit()
        return reservation
    
    def cancel_reservation(self, reservation_id):
        """取消预订"""
        reservation = self.get_by_id(reservation_id)
        if not reservation:
            return None
        
        if reservation.status == 4:
            raise ValueError('预订已取消')
        
        reservation.status = 4  # 已取消
        db.session.commit()
        return reservation
    
    def check_in_reservation(self, reservation_id):
        """办理入住"""
        reservation = self.get_by_id(reservation_id)
        if not reservation:
            return None
        
        if reservation.status != 2:
            raise ValueError('只有已确认的预订才能入住')
        
        reservation.status = 3  # 已入住
        db.session.commit()
        return reservation
    
    def get_upcoming_checkins(self, days=7):
        """获取即将入住的预订"""
        from datetime import timedelta
        
        start_date = datetime.now()
        end_date = start_date + timedelta(days=days)
        
        return Reservation.query.filter(
            Reservation.status.in_([1, 2]),  # 待确认或已确认
            Reservation.check_in >= start_date,
            Reservation.check_in <= end_date
        ).options(
            joinedload(Reservation.guest),
            joinedload(Reservation.room)
        ).all()
    
    def get_latest_reservations(self, limit=10):
        """获取最新预订"""
        return Reservation.query.order_by(Reservation.created_at.desc()).limit(limit).options(
            joinedload(Reservation.guest),
            joinedload(Reservation.room)
        ).all()
    
    def get_reservations_paginated_dto(self, page=1, per_page=10, room_number=None, status=None, 
                                       check_in_start=None, check_in_end=None):
        """获取预订列表（返回DTO）"""
        paginated = self.get_reservations_with_filters(page, per_page, room_number, status, check_in_start, check_in_end)
        return {
            'list': [self.mapper.to_dict(res) for res in paginated.items],
            'total': paginated.total,
            'page': paginated.page,
            'pageSize': paginated.per_page,
            'pages': paginated.pages
        }
    
    def get_reservation_dto(self, reservation_id):
        """获取预订详情（返回DTO）"""
        reservation = self.get_reservation_detail(reservation_id)
        return self.mapper.to_dict(reservation) if reservation else None
    
    def create_reservation_dto(self, guest_id, room_id, check_in, check_out, total_price, deposit=0):
        """创建预订（返回DTO）"""
        reservation = self.create_reservation(guest_id, room_id, check_in, check_out, total_price, deposit)
        return self.mapper.to_dict(reservation)
    
    def update_reservation_dto(self, reservation_id, **data):
        """更新预订（返回DTO）"""
        reservation = self.update_reservation(reservation_id, **data)
        return self.mapper.to_dict(reservation) if reservation else None
    
    def delete(self, reservation_id):
        """删除预订"""
        reservation = self.get_by_id(reservation_id)
        if not reservation:
            return False
        
        db.session.delete(reservation)
        db.session.commit()
        return True
